




//////////////////////////////////////////////////////////////////////////////
 #ifndef CODELITE_SMART_PTR_H
#define CODELITE_SMART_PTR_H


template <class T>
class SmartPtr
{
	
	class SmartPtrRef
	{
		T* m_data;
		int m_refCount;

	public:
		
		SmartPtrRef(T* data)
			: m_data( data )
			, m_refCount( 1 )
		{
		}

		
		virtual ~SmartPtrRef()
		{
			delete m_data;
		}

		
		T* GetData() { return m_data; }
        
        const T* GetData() const { return m_data; }
		
		void IncRef() { m_refCount ++ ; }


		
		void DecRef() { m_refCount -- ; }
		
		int  GetRefCount() { return m_refCount; }
	};

	SmartPtrRef *m_ref;

public:
	
	SmartPtr(T* ptr)
	{
	
		CreateFresh( ptr );
	}
	
	
	SmartPtr()
		: m_ref(NULL)
	{
	}

	
	SmartPtr(const SmartPtr& rhs)
		: m_ref(NULL)
	{
		*this = rhs;
	}

	
	SmartPtr& operator=(const SmartPtr& rhs)
	{
	
		if( m_ref == rhs.m_ref )
			return *this;

	
		DeleteRefCount();

		if( !rhs.m_ref )
			return *this;

		m_ref = rhs.m_ref;
		if (m_ref) {
			m_ref->IncRef();
		}
		return *this;
	}

	
	virtual ~SmartPtr()
	{
		DeleteRefCount();
	}

	
	void reset(T* ptr)
	{	
		DeleteRefCount();
		CreateFresh( ptr );
	}

	
	T* get()
	{
		return m_ref->GetData();
	}
    
    const T* get() const 
    {
        return m_ref->GetData();
    }
	
	T* operator->() const 
	{
		return m_ref->GetData();
	}

	
	T& operator*() const
	{
		return *(m_ref->GetData());
	}

	
	bool operator!() const
	{
		if( !m_ref )
			return true;

		return m_ref->GetData() == NULL;
	}

	
	operator bool() const
	{
		return m_ref && m_ref->GetData();
	}

private:
	void DeleteRefCount()
	{
	
		if( m_ref )
		{
			if( m_ref->GetRefCount() == 1 )
			{
				delete m_ref;
				m_ref = NULL;
			}
			else
				m_ref->DecRef();
		}
	};

	void CreateFresh(T* ptr)
	{
		m_ref = new SmartPtrRef( ptr );
	}
};


#endif // CODELITE_SMART_PTR_H
